{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "63384c33-081b-45e6-8b76-0f8df77d6de2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# pytorch 模型 保存完整模型，triton推理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6e4152ae-fcbd-4733-a267-205bcd43c556",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hit:1 http://mirrors.tencent.com/ubuntu bionic InRelease\n",
      "Hit:2 http://mirrors.tencent.com/ubuntu bionic-security InRelease              \u001b[0m\n",
      "Hit:3 http://mirrors.tencent.com/ubuntu bionic-updates InRelease               \u001b[0m\n",
      "Hit:4 http://ppa.launchpad.net/deadsnakes/ppa/ubuntu bionic InRelease  \u001b[0m    \u001b[0m\u001b[33m\u001b[33m\u001b[33m\n",
      "Hit:5 https://deb.nodesource.com/node_16.x bionic InRelease                 \u001b[0m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\u001b[33m\n",
      "Reading package lists... Done\u001b[0m                \u001b[33m\n",
      "Building dependency tree       \n",
      "Reading state information... Done\n",
      "102 packages can be upgraded. Run 'apt list --upgradable' to see them.\n",
      "Reading package lists... Done\n",
      "Building dependency tree       \n",
      "Reading state information... Done\n",
      "wget is already the newest version (1.19.4-1ubuntu2.2).\n",
      "Suggested packages:\n",
      "  zip\n",
      "The following NEW packages will be installed:\n",
      "  unzip\n",
      "0 upgraded, 1 newly installed, 0 to remove and 102 not upgraded.\n",
      "Need to get 168 kB of archives.\n",
      "After this operation, 567 kB of additional disk space will be used.\n",
      "Get:1 http://mirrors.tencent.com/ubuntu bionic-security/main amd64 unzip amd64 6.0-21ubuntu1.1 [168 kB]\n",
      "Fetched 168 kB in 0s (534 kB/s)[0m\u001b[33m\n",
      "debconf: delaying package configuration, since apt-utils is not installed\n",
      "\n",
      "\u001b7\u001b[0;23r\u001b8\u001b[1ASelecting previously unselected package unzip.\n",
      "(Reading database ... 25422 files and directories currently installed.)\n",
      "Preparing to unpack .../unzip_6.0-21ubuntu1.1_amd64.deb ...\n",
      "\u001b7\u001b[24;0f\u001b[42m\u001b[30mProgress: [  0%]\u001b[49m\u001b[39m [..........................................................] \u001b8\u001b7\u001b[24;0f\u001b[42m\u001b[30mProgress: [ 17%]\u001b[49m\u001b[39m [#########.................................................] \u001b8Unpacking unzip (6.0-21ubuntu1.1) ...\n",
      "\u001b7\u001b[24;0f\u001b[42m\u001b[30mProgress: [ 33%]\u001b[49m\u001b[39m [###################.......................................] \u001b8\u001b7\u001b[24;0f\u001b[42m\u001b[30mProgress: [ 50%]\u001b[49m\u001b[39m [#############################.............................] \u001b8Setting up unzip (6.0-21ubuntu1.1) ...\n",
      "\u001b7\u001b[24;0f\u001b[42m\u001b[30mProgress: [ 67%]\u001b[49m\u001b[39m [######################################....................] \u001b8\u001b7\u001b[24;0f\u001b[42m\u001b[30mProgress: [ 83%]\u001b[49m\u001b[39m [################################################..........] \u001b8Processing triggers for mime-support (3.60ubuntu1) ...\n",
      "\n",
      "\u001b7\u001b[0;24r\u001b8\u001b[1A\u001b[JLooking in indexes: https://mirrors.tencent.com/pypi/simple/, https://mirrors.tencent.com/repository/pypi/tencent_pypi/simple\n",
      "Collecting torchvision\n",
      "  Downloading https://mirrors.tencent.com/pypi/packages/18/2c/aa3f3193ea406aac402d9fcd30b07246cac096cf8e62d31d43c209b4adfd/torchvision-0.13.0-cp38-cp38-manylinux1_x86_64.whl (19.1 MB)\n",
      "     |████████████████████████████████| 19.1 MB 4.3 MB/s            \n",
      "\u001b[?25hCollecting torch\n",
      "  Downloading https://mirrors.tencent.com/pypi/packages/86/c3/30eb447a38bb73d57883ec0941e213249b2001d78332a3026351e0ee8d1f/torch-1.12.0-cp38-cp38-manylinux1_x86_64.whl (776.3 MB)\n",
      "     |████████████████████████████████| 776.3 MB 9.8 kB/s            \n",
      "\u001b[?25hRequirement already satisfied: typing-extensions in /usr/local/lib/python3.8/dist-packages (from torchvision) (4.0.1)\n",
      "Requirement already satisfied: requests in /usr/local/lib/python3.8/dist-packages (from torchvision) (2.27.1)\n",
      "Requirement already satisfied: numpy in /usr/local/lib/python3.8/dist-packages (from torchvision) (1.22.1)\n",
      "Collecting pillow!=8.3.*,>=5.3.0\n",
      "  Downloading https://mirrors.tencent.com/pypi/packages/20/cb/261342854f01ff18281e97ec8e6a7ce3beaf8e1091d1cebd52776049358d/Pillow-9.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)\n",
      "     |████████████████████████████████| 3.1 MB 990 kB/s            \n",
      "\u001b[?25hRequirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.8/dist-packages (from requests->torchvision) (1.26.5)\n",
      "Requirement already satisfied: charset-normalizer~=2.0.0 in /usr/local/lib/python3.8/dist-packages (from requests->torchvision) (2.0.10)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.8/dist-packages (from requests->torchvision) (3.3)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.8/dist-packages (from requests->torchvision) (2021.10.8)\n",
      "Installing collected packages: torch, pillow, torchvision\n",
      "Successfully installed pillow-9.2.0 torch-1.12.0 torchvision-0.13.0\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\n",
      "\u001b[33mWARNING: You are using pip version 21.3.1; however, version 22.2 is available.\n",
      "You should consider upgrading via the '/usr/bin/python -m pip install --upgrade pip' command.\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "! apt update -y\n",
    "! apt install -y wget unzip\n",
    "! pip install torchvision torch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7ce28849-4c67-4af7-a8fc-904c181d9194",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--2022-07-30 12:23:36--  https://cube-studio.oss-cn-hangzhou.aliyuncs.com/inference/resnet50.pth\n",
      "Resolving docker-76009.sz.gfp.tencent-cloud.com (docker-76009.sz.gfp.tencent-cloud.com)... 43.137.222.31, 175.27.38.240, 43.137.221.26, ...\n",
      "Connecting to docker-76009.sz.gfp.tencent-cloud.com (docker-76009.sz.gfp.tencent-cloud.com)|43.137.222.31|:443... connected.\n",
      "HTTP request sent, awaiting response... 200 OK\n",
      "Length: 102530333 (98M) [application/octet-stream]\n",
      "Saving to: ‘resnet50.pth’\n",
      "\n",
      "resnet50.pth        100%[===================>]  97.78M  6.42MB/s    in 15s     \n",
      "\n",
      "2022-07-30 12:23:52 (6.54 MB/s) - ‘resnet50.pth’ saved [102530333/102530333]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# triton 直接推理 torch模型\n",
    "! rm -rf resnet50.pth && wget https://cube-studio.oss-cn-hangzhou.aliyuncs.com/inference/resnet50.pth"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "0a853810-b2c7-49f6-a36e-713121133ee1",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.8/dist-packages/torchvision/models/_utils.py:208: UserWarning: The parameter 'pretrained' is deprecated since 0.13 and will be removed in 0.15, please use 'weights' instead.\n",
      "  warnings.warn(\n",
      "/usr/local/lib/python3.8/dist-packages/torchvision/models/_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and will be removed in 0.15. The current behavior is equivalent to passing `weights=None`.\n",
      "  warnings.warn(msg)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ResNet(\n",
      "  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)\n",
      "  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "  (relu): ReLU(inplace=True)\n",
      "  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)\n",
      "  (layer1): Sequential(\n",
      "    (0): Bottleneck(\n",
      "      (conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "      (downsample): Sequential(\n",
      "        (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      )\n",
      "    )\n",
      "    (1): Bottleneck(\n",
      "      (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "    (2): Bottleneck(\n",
      "      (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "  )\n",
      "  (layer2): Sequential(\n",
      "    (0): Bottleneck(\n",
      "      (conv1): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "      (downsample): Sequential(\n",
      "        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
      "        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      )\n",
      "    )\n",
      "    (1): Bottleneck(\n",
      "      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "    (2): Bottleneck(\n",
      "      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "    (3): Bottleneck(\n",
      "      (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "  )\n",
      "  (layer3): Sequential(\n",
      "    (0): Bottleneck(\n",
      "      (conv1): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "      (downsample): Sequential(\n",
      "        (0): Conv2d(512, 1024, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
      "        (1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      )\n",
      "    )\n",
      "    (1): Bottleneck(\n",
      "      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "    (2): Bottleneck(\n",
      "      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "    (3): Bottleneck(\n",
      "      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "    (4): Bottleneck(\n",
      "      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "    (5): Bottleneck(\n",
      "      (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "  )\n",
      "  (layer4): Sequential(\n",
      "    (0): Bottleneck(\n",
      "      (conv1): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "      (downsample): Sequential(\n",
      "        (0): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
      "        (1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      )\n",
      "    )\n",
      "    (1): Bottleneck(\n",
      "      (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "    (2): Bottleneck(\n",
      "      (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "      (relu): ReLU(inplace=True)\n",
      "    )\n",
      "  )\n",
      "  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))\n",
      "  (fc): Linear(in_features=2048, out_features=1000, bias=True)\n",
      ")\n",
      "conv1.weight : torch.Size([64, 3, 7, 7])\n",
      "bn1.weight : torch.Size([64])\n",
      "bn1.bias : torch.Size([64])\n",
      "layer1.0.conv1.weight : torch.Size([64, 64, 1, 1])\n",
      "layer1.0.bn1.weight : torch.Size([64])\n",
      "layer1.0.bn1.bias : torch.Size([64])\n",
      "layer1.0.conv2.weight : torch.Size([64, 64, 3, 3])\n",
      "layer1.0.bn2.weight : torch.Size([64])\n",
      "layer1.0.bn2.bias : torch.Size([64])\n",
      "layer1.0.conv3.weight : torch.Size([256, 64, 1, 1])\n",
      "layer1.0.bn3.weight : torch.Size([256])\n",
      "layer1.0.bn3.bias : torch.Size([256])\n",
      "layer1.0.downsample.0.weight : torch.Size([256, 64, 1, 1])\n",
      "layer1.0.downsample.1.weight : torch.Size([256])\n",
      "layer1.0.downsample.1.bias : torch.Size([256])\n",
      "layer1.1.conv1.weight : torch.Size([64, 256, 1, 1])\n",
      "layer1.1.bn1.weight : torch.Size([64])\n",
      "layer1.1.bn1.bias : torch.Size([64])\n",
      "layer1.1.conv2.weight : torch.Size([64, 64, 3, 3])\n",
      "layer1.1.bn2.weight : torch.Size([64])\n",
      "layer1.1.bn2.bias : torch.Size([64])\n",
      "layer1.1.conv3.weight : torch.Size([256, 64, 1, 1])\n",
      "layer1.1.bn3.weight : torch.Size([256])\n",
      "layer1.1.bn3.bias : torch.Size([256])\n",
      "layer1.2.conv1.weight : torch.Size([64, 256, 1, 1])\n",
      "layer1.2.bn1.weight : torch.Size([64])\n",
      "layer1.2.bn1.bias : torch.Size([64])\n",
      "layer1.2.conv2.weight : torch.Size([64, 64, 3, 3])\n",
      "layer1.2.bn2.weight : torch.Size([64])\n",
      "layer1.2.bn2.bias : torch.Size([64])\n",
      "layer1.2.conv3.weight : torch.Size([256, 64, 1, 1])\n",
      "layer1.2.bn3.weight : torch.Size([256])\n",
      "layer1.2.bn3.bias : torch.Size([256])\n",
      "layer2.0.conv1.weight : torch.Size([128, 256, 1, 1])\n",
      "layer2.0.bn1.weight : torch.Size([128])\n",
      "layer2.0.bn1.bias : torch.Size([128])\n",
      "layer2.0.conv2.weight : torch.Size([128, 128, 3, 3])\n",
      "layer2.0.bn2.weight : torch.Size([128])\n",
      "layer2.0.bn2.bias : torch.Size([128])\n",
      "layer2.0.conv3.weight : torch.Size([512, 128, 1, 1])\n",
      "layer2.0.bn3.weight : torch.Size([512])\n",
      "layer2.0.bn3.bias : torch.Size([512])\n",
      "layer2.0.downsample.0.weight : torch.Size([512, 256, 1, 1])\n",
      "layer2.0.downsample.1.weight : torch.Size([512])\n",
      "layer2.0.downsample.1.bias : torch.Size([512])\n",
      "layer2.1.conv1.weight : torch.Size([128, 512, 1, 1])\n",
      "layer2.1.bn1.weight : torch.Size([128])\n",
      "layer2.1.bn1.bias : torch.Size([128])\n",
      "layer2.1.conv2.weight : torch.Size([128, 128, 3, 3])\n",
      "layer2.1.bn2.weight : torch.Size([128])\n",
      "layer2.1.bn2.bias : torch.Size([128])\n",
      "layer2.1.conv3.weight : torch.Size([512, 128, 1, 1])\n",
      "layer2.1.bn3.weight : torch.Size([512])\n",
      "layer2.1.bn3.bias : torch.Size([512])\n",
      "layer2.2.conv1.weight : torch.Size([128, 512, 1, 1])\n",
      "layer2.2.bn1.weight : torch.Size([128])\n",
      "layer2.2.bn1.bias : torch.Size([128])\n",
      "layer2.2.conv2.weight : torch.Size([128, 128, 3, 3])\n",
      "layer2.2.bn2.weight : torch.Size([128])\n",
      "layer2.2.bn2.bias : torch.Size([128])\n",
      "layer2.2.conv3.weight : torch.Size([512, 128, 1, 1])\n",
      "layer2.2.bn3.weight : torch.Size([512])\n",
      "layer2.2.bn3.bias : torch.Size([512])\n",
      "layer2.3.conv1.weight : torch.Size([128, 512, 1, 1])\n",
      "layer2.3.bn1.weight : torch.Size([128])\n",
      "layer2.3.bn1.bias : torch.Size([128])\n",
      "layer2.3.conv2.weight : torch.Size([128, 128, 3, 3])\n",
      "layer2.3.bn2.weight : torch.Size([128])\n",
      "layer2.3.bn2.bias : torch.Size([128])\n",
      "layer2.3.conv3.weight : torch.Size([512, 128, 1, 1])\n",
      "layer2.3.bn3.weight : torch.Size([512])\n",
      "layer2.3.bn3.bias : torch.Size([512])\n",
      "layer3.0.conv1.weight : torch.Size([256, 512, 1, 1])\n",
      "layer3.0.bn1.weight : torch.Size([256])\n",
      "layer3.0.bn1.bias : torch.Size([256])\n",
      "layer3.0.conv2.weight : torch.Size([256, 256, 3, 3])\n",
      "layer3.0.bn2.weight : torch.Size([256])\n",
      "layer3.0.bn2.bias : torch.Size([256])\n",
      "layer3.0.conv3.weight : torch.Size([1024, 256, 1, 1])\n",
      "layer3.0.bn3.weight : torch.Size([1024])\n",
      "layer3.0.bn3.bias : torch.Size([1024])\n",
      "layer3.0.downsample.0.weight : torch.Size([1024, 512, 1, 1])\n",
      "layer3.0.downsample.1.weight : torch.Size([1024])\n",
      "layer3.0.downsample.1.bias : torch.Size([1024])\n",
      "layer3.1.conv1.weight : torch.Size([256, 1024, 1, 1])\n",
      "layer3.1.bn1.weight : torch.Size([256])\n",
      "layer3.1.bn1.bias : torch.Size([256])\n",
      "layer3.1.conv2.weight : torch.Size([256, 256, 3, 3])\n",
      "layer3.1.bn2.weight : torch.Size([256])\n",
      "layer3.1.bn2.bias : torch.Size([256])\n",
      "layer3.1.conv3.weight : torch.Size([1024, 256, 1, 1])\n",
      "layer3.1.bn3.weight : torch.Size([1024])\n",
      "layer3.1.bn3.bias : torch.Size([1024])\n",
      "layer3.2.conv1.weight : torch.Size([256, 1024, 1, 1])\n",
      "layer3.2.bn1.weight : torch.Size([256])\n",
      "layer3.2.bn1.bias : torch.Size([256])\n",
      "layer3.2.conv2.weight : torch.Size([256, 256, 3, 3])\n",
      "layer3.2.bn2.weight : torch.Size([256])\n",
      "layer3.2.bn2.bias : torch.Size([256])\n",
      "layer3.2.conv3.weight : torch.Size([1024, 256, 1, 1])\n",
      "layer3.2.bn3.weight : torch.Size([1024])\n",
      "layer3.2.bn3.bias : torch.Size([1024])\n",
      "layer3.3.conv1.weight : torch.Size([256, 1024, 1, 1])\n",
      "layer3.3.bn1.weight : torch.Size([256])\n",
      "layer3.3.bn1.bias : torch.Size([256])\n",
      "layer3.3.conv2.weight : torch.Size([256, 256, 3, 3])\n",
      "layer3.3.bn2.weight : torch.Size([256])\n",
      "layer3.3.bn2.bias : torch.Size([256])\n",
      "layer3.3.conv3.weight : torch.Size([1024, 256, 1, 1])\n",
      "layer3.3.bn3.weight : torch.Size([1024])\n",
      "layer3.3.bn3.bias : torch.Size([1024])\n",
      "layer3.4.conv1.weight : torch.Size([256, 1024, 1, 1])\n",
      "layer3.4.bn1.weight : torch.Size([256])\n",
      "layer3.4.bn1.bias : torch.Size([256])\n",
      "layer3.4.conv2.weight : torch.Size([256, 256, 3, 3])\n",
      "layer3.4.bn2.weight : torch.Size([256])\n",
      "layer3.4.bn2.bias : torch.Size([256])\n",
      "layer3.4.conv3.weight : torch.Size([1024, 256, 1, 1])\n",
      "layer3.4.bn3.weight : torch.Size([1024])\n",
      "layer3.4.bn3.bias : torch.Size([1024])\n",
      "layer3.5.conv1.weight : torch.Size([256, 1024, 1, 1])\n",
      "layer3.5.bn1.weight : torch.Size([256])\n",
      "layer3.5.bn1.bias : torch.Size([256])\n",
      "layer3.5.conv2.weight : torch.Size([256, 256, 3, 3])\n",
      "layer3.5.bn2.weight : torch.Size([256])\n",
      "layer3.5.bn2.bias : torch.Size([256])\n",
      "layer3.5.conv3.weight : torch.Size([1024, 256, 1, 1])\n",
      "layer3.5.bn3.weight : torch.Size([1024])\n",
      "layer3.5.bn3.bias : torch.Size([1024])\n",
      "layer4.0.conv1.weight : torch.Size([512, 1024, 1, 1])\n",
      "layer4.0.bn1.weight : torch.Size([512])\n",
      "layer4.0.bn1.bias : torch.Size([512])\n",
      "layer4.0.conv2.weight : torch.Size([512, 512, 3, 3])\n",
      "layer4.0.bn2.weight : torch.Size([512])\n",
      "layer4.0.bn2.bias : torch.Size([512])\n",
      "layer4.0.conv3.weight : torch.Size([2048, 512, 1, 1])\n",
      "layer4.0.bn3.weight : torch.Size([2048])\n",
      "layer4.0.bn3.bias : torch.Size([2048])\n",
      "layer4.0.downsample.0.weight : torch.Size([2048, 1024, 1, 1])\n",
      "layer4.0.downsample.1.weight : torch.Size([2048])\n",
      "layer4.0.downsample.1.bias : torch.Size([2048])\n",
      "layer4.1.conv1.weight : torch.Size([512, 2048, 1, 1])\n",
      "layer4.1.bn1.weight : torch.Size([512])\n",
      "layer4.1.bn1.bias : torch.Size([512])\n",
      "layer4.1.conv2.weight : torch.Size([512, 512, 3, 3])\n",
      "layer4.1.bn2.weight : torch.Size([512])\n",
      "layer4.1.bn2.bias : torch.Size([512])\n",
      "layer4.1.conv3.weight : torch.Size([2048, 512, 1, 1])\n",
      "layer4.1.bn3.weight : torch.Size([2048])\n",
      "layer4.1.bn3.bias : torch.Size([2048])\n",
      "layer4.2.conv1.weight : torch.Size([512, 2048, 1, 1])\n",
      "layer4.2.bn1.weight : torch.Size([512])\n",
      "layer4.2.bn1.bias : torch.Size([512])\n",
      "layer4.2.conv2.weight : torch.Size([512, 512, 3, 3])\n",
      "layer4.2.bn2.weight : torch.Size([512])\n",
      "layer4.2.bn2.bias : torch.Size([512])\n",
      "layer4.2.conv3.weight : torch.Size([2048, 512, 1, 1])\n",
      "layer4.2.bn3.weight : torch.Size([2048])\n",
      "layer4.2.bn3.bias : torch.Size([2048])\n",
      "fc.weight : torch.Size([1000, 2048])\n",
      "fc.bias : torch.Size([1000])\n"
     ]
    }
   ],
   "source": [
    "from torchvision import models\n",
    "# from torchsummary import summary\n",
    "import torch\n",
    "from torchvision.models.resnet import resnet50\n",
    "device = torch.device('cpu')\n",
    "\n",
    "model = resnet50(pretrained=False, progress=True)   # 创建模型\n",
    "model.load_state_dict(torch.load(\"resnet50.pth\",map_location='cpu')) # 加载模型参数\n",
    "\n",
    "# 查看模型结构\n",
    "print(model)\n",
    "\n",
    "# 查看模型参数\n",
    "for name, parameters in model.named_parameters():\n",
    "    print(name, ':', parameters.size())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0bbad94a-435d-40f4-8e86-8eabd9af1d5c",
   "metadata": {},
   "outputs": [],
   "source": [
    "!rm -rf resnet50.onnx torchscript.pt\n",
    "\n",
    "model.eval()     # 设置模型为推理模式\n",
    "\n",
    "# 导出网络到ONNX，需提供输入输出名\n",
    "dummy_input = torch.randn(1, 3, 224, 224).to(device)  # 输入样本\n",
    "torch.onnx.export(\n",
    "    model,dummy_input,\"resnet50.onnx\",\n",
    "    opset_version=13,           # 转为onnx的版本\n",
    "    do_constant_folding=True,   # 是否执行常量折叠优化\n",
    "    input_names=[\"input_name\"],     # 输入名\n",
    "    output_names=[\"output_name\"],   # 输出名\n",
    "    # dynamic_axes={\n",
    "    #     \"input\":{0:\"batch_size\"},   # 批处理变量\n",
    "    #     \"output\":{0:\"batch_size\"}\n",
    "    # },\n",
    "    # dynamic_axes={'input_name': [2, 3], 'output_name': [2, 3]}   # 动态size的输入输出的维度\n",
    ")\n",
    "\n",
    "\n",
    "# 保存TORCHSCRIPT\n",
    "# torch script保存的模型，目前不提供输入和输出的端口的命名，\n",
    "# 因此在配置文件中，输入和输出端口的名字必须按照如下命名： \"INPUT__0\", \"INPUT__1\" and \"OUTPUT__0\", \"OUTPUT__1\"\n",
    "dummy_input = torch.randn(1, 3, 224, 224).to(device)  # 输入样本\n",
    "traced_cell = torch.jit.trace(model, dummy_input)\n",
    "traced_cell.save(\"resnet50-torchscript.pt\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a4b72b53-407b-4efd-98ab-34d738a6da67",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 配置pytorch模型 config.pbtxt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "84dd9529-7113-49a5-aa6c-c3f22a85340c",
   "metadata": {},
   "outputs": [],
   "source": [
    "name: \"resnet50\"\n",
    "platform: \"pytorch_libtorch\"\n",
    "max_batch_size : 0\n",
    "input [\n",
    "  {\n",
    "    name: \"INPUT__0\"\n",
    "    data_type: TYPE_FP32\n",
    "    format: FORMAT_NCHW\n",
    "    dims: [ 3, 224, 224 ]\n",
    "    reshape { shape: [ 1, 3, 224, 224 ] }\n",
    "  }\n",
    "]\n",
    "output [\n",
    "  {\n",
    "    name: \"OUTPUT__0\"\n",
    "    data_type: TYPE_FP32\n",
    "    dims: [ 1000 ]\n",
    "    reshape { shape: [ 1, 1000, 1, 1 ] }\n",
    "  }\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c05fb5cc-5a0b-4501-8a2c-5123e5c181b5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# pytorch 转为onnx 使用triton 推理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "ba522eab-ed7e-493d-8b95-25b2d3a0678b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://mirrors.tencent.com/pypi/simple/, https://mirrors.tencent.com/repository/pypi/tencent_pypi/simple\n",
      "Collecting netron\n",
      "  Downloading https://mirrors.tencent.com/pypi/packages/4c/2d/afa00587db942b710033a2362d7afff16b739af955c520a80ee21c8db28b/netron-5.9.4-py3-none-any.whl (1.5 MB)\n",
      "     |████████████████████████████████| 1.5 MB 811 kB/s            \n",
      "\u001b[?25hInstalling collected packages: netron\n",
      "Successfully installed netron-5.9.4\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\n",
      "\u001b[33mWARNING: You are using pip version 21.3.1; however, version 22.2 is available.\n",
      "You should consider upgrading via the '/usr/bin/python -m pip install --upgrade pip' command.\u001b[0m\n",
      "Serving 'resnet50.onnx' at http://localhost:8080\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "('localhost', 8080)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "! pip install onnx netron\n",
    "# 查看网络模型结构\n",
    "import netron\n",
    "modelPath = \"resnet50.onnx\"\n",
    "netron.start(modelPath)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4d146a93-5f3f-48bc-95a3-3316e0d6548d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 配置onnx模型 config.pbtxt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "88e289e8-0c1e-4990-8152-b885f05ff88b",
   "metadata": {},
   "outputs": [],
   "source": [
    "name: \"resnet50\"\n",
    "platform: \"onnxruntime_onnx\"\n",
    "backend: \"onnxruntime\"\n",
    "max_batch_size : 0\n",
    "\n",
    "input [\n",
    "  {\n",
    "    name: \"input_name\"\n",
    "    data_type: TYPE_FP32\n",
    "    format: FORMAT_NCHW\n",
    "    dims: [ 3, 224, 224 ]\n",
    "    reshape { shape: [ 1, 3, 224, 224 ] }\n",
    "  }\n",
    "]\n",
    "output [\n",
    "  {\n",
    "    name: \"output_name\"\n",
    "    data_type: TYPE_FP32\n",
    "    dims: [ 1000 ]\n",
    "    reshape { shape: [ 1, 1000 ] }\n",
    "  }\n",
    "]\n",
    "\n",
    "parameters { key: \"intra_op_thread_count\" value: { string_value: \"10\" } }\n",
    "parameters { key: \"execution_mode\" value: { string_value: \"1\" } }\n",
    "parameters { key: \"inter_op_thread_count\" value: { string_value: \"10\" } }\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "74e98673-cb92-4b3f-ac12-5730c668248e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://mirrors.tencent.com/pypi/simple/, https://mirrors.tencent.com/repository/pypi/tencent_pypi/simple\n",
      "Requirement already satisfied: tritonclient[all] in /usr/local/lib/python3.8/dist-packages (2.23.0)\n",
      "Requirement already satisfied: pysnooper in /usr/local/lib/python3.8/dist-packages (1.1.0)\n",
      "Requirement already satisfied: requests in /usr/local/lib/python3.8/dist-packages (2.27.1)\n",
      "Requirement already satisfied: Pillow in /usr/local/lib/python3.8/dist-packages (9.2.0)\n",
      "Collecting attrdict\n",
      "  Downloading https://mirrors.tencent.com/pypi/packages/ef/97/28fe7e68bc7adfce67d4339756e85e9fcf3c6fd7f0c0781695352b70472c/attrdict-2.0.1-py2.py3-none-any.whl (9.9 kB)\n",
      "Requirement already satisfied: numpy>=1.19.1 in /usr/local/lib/python3.8/dist-packages (from tritonclient[all]) (1.22.1)\n",
      "Requirement already satisfied: python-rapidjson>=0.9.1 in /usr/local/lib/python3.8/dist-packages (from tritonclient[all]) (1.8)\n",
      "Requirement already satisfied: grpcio==1.41.0 in /usr/local/lib/python3.8/dist-packages (from tritonclient[all]) (1.41.0)\n",
      "Requirement already satisfied: protobuf<3.20,>=3.5.0 in /usr/local/lib/python3.8/dist-packages (from tritonclient[all]) (3.19.3)\n",
      "Requirement already satisfied: geventhttpclient>=1.4.4 in /usr/local/lib/python3.8/dist-packages (from tritonclient[all]) (1.5.5)\n",
      "Requirement already satisfied: six>=1.5.2 in /usr/local/lib/python3.8/dist-packages (from grpcio==1.41.0->tritonclient[all]) (1.16.0)\n",
      "Requirement already satisfied: charset-normalizer~=2.0.0 in /usr/local/lib/python3.8/dist-packages (from requests) (2.0.10)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.8/dist-packages (from requests) (2021.10.8)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.8/dist-packages (from requests) (3.3)\n",
      "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.8/dist-packages (from requests) (1.26.5)\n",
      "Requirement already satisfied: gevent>=0.13 in /usr/local/lib/python3.8/dist-packages (from geventhttpclient>=1.4.4->tritonclient[all]) (21.12.0)\n",
      "Requirement already satisfied: brotli in /usr/local/lib/python3.8/dist-packages (from geventhttpclient>=1.4.4->tritonclient[all]) (1.0.9)\n",
      "Requirement already satisfied: zope.interface in /usr/local/lib/python3.8/dist-packages (from gevent>=0.13->geventhttpclient>=1.4.4->tritonclient[all]) (5.4.0)\n",
      "Requirement already satisfied: greenlet<2.0,>=1.1.0 in /usr/local/lib/python3.8/dist-packages (from gevent>=0.13->geventhttpclient>=1.4.4->tritonclient[all]) (1.1.2)\n",
      "Requirement already satisfied: zope.event in /usr/local/lib/python3.8/dist-packages (from gevent>=0.13->geventhttpclient>=1.4.4->tritonclient[all]) (4.5.0)\n",
      "Requirement already satisfied: setuptools in /usr/local/lib/python3.8/dist-packages (from gevent>=0.13->geventhttpclient>=1.4.4->tritonclient[all]) (60.5.0)\n",
      "Installing collected packages: attrdict\n",
      "Successfully installed attrdict-2.0.1\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\n",
      "\u001b[33mWARNING: You are using pip version 21.3.1; however, version 22.2 is available.\n",
      "You should consider upgrading via the '/usr/bin/python -m pip install --upgrade pip' command.\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "!pip install tritonclient[all] pysnooper requests Pillow attrdict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "1cedfb28-241d-43ea-8b07-9933a7fb9e4c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "模型信息： {'name': 'resnet50', 'versions': ['202208013'], 'platform': 'pytorch_libtorch', 'inputs': [{'name': 'INPUT__0', 'datatype': 'FP32', 'shape': [3, 224, 224]}], 'outputs': [{'name': 'OUTPUT__0', 'datatype': 'FP32', 'shape': [1000]}]}\n",
      "模型配置： {'name': 'resnet50', 'platform': 'pytorch_libtorch', 'backend': 'pytorch', 'version_policy': {'latest': {'num_versions': 1}}, 'max_batch_size': 0, 'input': [{'name': 'INPUT__0', 'data_type': 'TYPE_FP32', 'format': 'FORMAT_NCHW', 'dims': [3, 224, 224], 'reshape': {'shape': [1, 3, 224, 224]}, 'is_shape_tensor': False, 'allow_ragged_batch': False, 'optional': False}], 'output': [{'name': 'OUTPUT__0', 'data_type': 'TYPE_FP32', 'dims': [1000], 'reshape': {'shape': [1, 1000]}, 'label_filename': '', 'is_shape_tensor': False}], 'batch_input': [], 'batch_output': [], 'optimization': {'priority': 'PRIORITY_DEFAULT', 'input_pinned_memory': {'enable': True}, 'output_pinned_memory': {'enable': True}, 'gather_kernel_buffer_threshold': 0, 'eager_batching': False}, 'instance_group': [{'name': 'resnet50', 'kind': 'KIND_CPU', 'count': 1, 'gpus': [], 'secondary_devices': [], 'profile': [], 'passive': False, 'host_policy': ''}], 'default_model_filename': 'model.pt', 'cc_model_filenames': {}, 'metric_tags': {}, 'parameters': {'INFERENCE_MODE': {'string_value': 'false'}, 'DISABLE_OPTIMIZED_EXECUTION': {'string_value': 'true'}}, 'model_warmup': []}\n",
      "请求参数： 0 INPUT__0 OUTPUT__0 3 224 224 2 FP32\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_135/624468017.py:114: DeprecationWarning: BILINEAR is deprecated and will be removed in Pillow 10 (2023-07-01). Use Resampling.BILINEAR instead.\n",
      "  resized_img = sample_img.resize((w, h), Image.BILINEAR)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "响应： 1000 [b'2146.752197:818' b'1593.821045:862' b'1580.508057:920'\n",
      " b'1497.157715:819' b'1446.738159:619' b'1390.396973:437'\n",
      " b'1384.841309:555' b'1364.949463:530' b'1294.385498:754'\n",
      " b'1257.208374:778' b'1255.856689:731' b'1251.588135:632'\n",
      " b'1234.268188:968' b'1149.677612:407' b'1127.524292:817'\n",
      " b'1120.258057:627' b'1090.039185:734' b'1083.440796:867'\n",
      " b'1057.487671:982' b'1046.120239:94' b'1030.905151:468'\n",
      " b'1016.339539:664' b'1014.331299:498' b'999.077209:479' b'998.746399:779'\n",
      " b'991.391113:656' b'974.361450:650' b'970.355469:745' b'968.627625:463'\n",
      " b'941.921936:800' b'937.423035:864' b'931.570801:579' b'931.442078:421'\n",
      " b'921.547119:685' b'909.909668:781' b'909.362976:617' b'906.689148:919'\n",
      " b'891.300781:837' b'889.427002:542' b'887.115845:782' b'877.967712:578'\n",
      " b'866.516235:644' b'863.522949:902' b'862.775574:412' b'861.634583:409'\n",
      " b'858.461487:557' b'855.091187:762' b'854.653076:799' b'850.362122:562'\n",
      " b'850.269531:899' b'837.659363:559' b'834.099609:718' b'833.294556:404'\n",
      " b'815.659851:916' b'814.179077:654' b'812.403625:900' b'811.897949:882'\n",
      " b'811.678223:620' b'809.714050:571' b'809.163940:527' b'808.774292:846'\n",
      " b'808.684631:829' b'796.039795:711' b'795.891602:531' b'795.385193:839'\n",
      " b'793.025879:460' b'788.068726:497' b'785.678345:908' b'783.165955:607'\n",
      " b'779.301086:836' b'778.678955:581' b'773.207886:736' b'771.440247:536'\n",
      " b'763.200928:733' b'753.418091:742' b'746.604980:760' b'741.320374:716'\n",
      " b'740.100525:854' b'728.802063:980' b'725.856934:572' b'725.147888:744'\n",
      " b'723.739319:907' b'716.864929:681' b'712.193237:966' b'709.229187:462'\n",
      " b'701.515137:626' b'701.057678:751' b'694.283203:546' b'691.270081:60'\n",
      " b'687.743835:827' b'685.725037:769' b'678.468384:435' b'677.163391:717'\n",
      " b'676.147949:402' b'675.855652:879' b'671.024536:673' b'658.869446:417'\n",
      " b'653.858276:628' b'653.157898:638' b'652.192017:538' b'650.701050:641'\n",
      " b'647.038757:704' b'643.183716:852' b'638.519653:840' b'637.155762:822'\n",
      " b'636.917603:826' b'632.139954:471' b'627.100281:254' b'623.778687:447'\n",
      " b'621.794495:541' b'621.620483:655' b'620.829163:523' b'609.947876:828'\n",
      " b'605.528137:896' b'604.099304:710' b'600.726990:506' b'599.337524:575'\n",
      " b'598.149536:757' b'589.631287:552' b'589.144409:480' b'587.730896:861'\n",
      " b'586.690857:569' b'585.638916:755' b'584.357361:876' b'582.335266:811'\n",
      " b'578.440247:886' b'574.364990:872' b'570.487549:518' b'569.141968:823'\n",
      " b'568.908752:962' b'565.169983:720' b'564.888245:723' b'559.542236:950'\n",
      " b'559.462830:441' b'556.214478:613' b'554.123474:440' b'553.865662:511'\n",
      " b'552.611389:504' b'552.369080:659' b'548.392395:625' b'546.688843:851'\n",
      " b'537.161011:470' b'536.652344:806' b'532.333008:427' b'532.320618:466'\n",
      " b'529.734009:696' b'529.451294:785' b'528.766724:299' b'528.598022:629'\n",
      " b'522.319336:812' b'520.872437:637' b'518.952026:869' b'517.028259:660'\n",
      " b'515.348450:436' b'513.294006:601' b'512.757874:705' b'512.289001:582'\n",
      " b'507.551086:880' b'501.610016:606' b'500.264099:517' b'499.712982:892'\n",
      " b'492.501343:457' b'491.908600:821' b'491.661346:898' b'489.891510:276'\n",
      " b'488.760712:737' b'486.863251:875' b'481.715424:670' b'473.971252:508'\n",
      " b'472.958252:971' b'472.192596:521' b'471.912109:666' b'467.154633:722'\n",
      " b'466.622528:725' b'465.815308:651' b'456.411957:505' b'455.602142:604'\n",
      " b'450.838409:570' b'448.806488:860' b'447.439178:791' b'442.580170:598'\n",
      " b'440.455353:554' b'439.591766:845' b'438.797974:475' b'438.560242:727'\n",
      " b'432.787811:453' b'432.192566:442' b'428.851990:694' b'428.051270:503'\n",
      " b'427.459900:373' b'423.857910:600' b'422.925049:657' b'422.357513:888'\n",
      " b'419.939911:682' b'419.383728:510' b'419.136017:469' b'417.483093:321'\n",
      " b'417.287109:868' b'417.277832:486' b'412.792755:960' b'407.749939:553'\n",
      " b'406.209900:935' b'405.666595:910' b'400.306763:515' b'394.899902:672'\n",
      " b'393.380219:645' b'392.186035:192' b'391.714966:814' b'391.621277:264'\n",
      " b'391.054291:643' b'387.020172:917' b'386.639160:544' b'385.867889:830'\n",
      " b'376.856079:844' b'370.562347:923' b'370.200531:485' b'369.586914:838'\n",
      " b'364.424805:928' b'361.451202:585' b'360.147308:784' b'358.607330:678'\n",
      " b'358.026337:937' b'355.763794:256' b'355.268097:847' b'354.850281:592'\n",
      " b'354.467285:714' b'354.130615:635' b'351.464447:599' b'350.629669:809'\n",
      " b'336.643829:897' b'336.244293:693' b'334.341461:883' b'332.051117:766'\n",
      " b'330.046814:526' b'327.677002:534' b'327.351868:804' b'326.777435:476'\n",
      " b'325.964905:909' b'325.615601:1' b'325.452393:807' b'321.100830:208'\n",
      " b'320.056976:773' b'317.813019:708' b'317.103607:761' b'315.952484:767'\n",
      " b'315.858856:958' b'311.868439:420' b'310.395935:455' b'309.338135:688'\n",
      " b'304.475128:513' b'303.552643:642' b'298.897400:283' b'298.791534:877'\n",
      " b'297.302399:610' b'294.747925:795' b'294.513489:155' b'293.812500:859'\n",
      " b'293.295563:926' b'292.960938:282' b'292.929840:459' b'291.972076:709'\n",
      " b'291.515961:924' b'287.135223:438' b'283.723846:605' b'282.726196:16'\n",
      " b'282.209045:813' b'274.363373:170' b'272.729218:398' b'270.299744:793'\n",
      " b'268.098877:298' b'266.016571:323' b'263.211823:622' b'259.167847:556'\n",
      " b'258.547455:566' b'255.969528:220' b'255.722488:889' b'254.935959:568'\n",
      " b'253.585129:796' b'252.212036:596' b'244.018723:464' b'242.964676:419'\n",
      " b'237.935623:418' b'236.074173:255' b'235.708466:832' b'234.646591:772'\n",
      " b'233.687271:454' b'229.610886:652' b'228.579300:509' b'226.174637:631'\n",
      " b'226.103012:224' b'219.738495:251' b'218.370926:401' b'216.703232:182'\n",
      " b'215.171463:561' b'211.625122:408' b'210.705872:281' b'209.094757:338'\n",
      " b'209.037750:805' b'208.042740:967' b'207.512634:750' b'206.991348:675'\n",
      " b'206.155792:602' b'205.683548:783' b'204.556946:903' b'203.376968:865'\n",
      " b'202.264587:938' b'199.144180:929' b'198.933273:235' b'198.086700:489'\n",
      " b'196.967468:732' b'195.289490:215' b'194.466522:848' b'193.895432:802'\n",
      " b'193.831741:567' b'191.013809:216' b'189.197113:747' b'188.889893:646'\n",
      " b'188.522842:245' b'188.478180:978' b'187.337601:904' b'187.248489:560'\n",
      " b'187.058762:185' b'184.814789:881' b'184.183701:946' b'183.882614:894'\n",
      " b'181.209808:243' b'180.314148:969' b'180.240189:873' b'178.564285:134'\n",
      " b'178.463867:665' b'176.210968:574' b'175.757614:545' b'174.711472:850'\n",
      " b'174.531570:771' b'173.009750:803' b'170.381882:154' b'168.078918:974'\n",
      " b'166.490891:186' b'166.266281:815' b'165.160950:841' b'164.823685:550'\n",
      " b'163.433456:372' b'159.615707:797' b'154.954514:758' b'154.159866:594'\n",
      " b'153.555267:415' b'151.431015:199' b'150.311768:949' b'149.424271:965'\n",
      " b'147.471786:740' b'146.511490:808' b'146.247040:380' b'145.010239:831'\n",
      " b'139.089783:301' b'137.524307:608' b'136.599258:957' b'131.620636:90'\n",
      " b'128.355728:984' b'127.982178:776' b'127.062279:934' b'126.243874:985'\n",
      " b'125.465836:918' b'121.863762:609' b'121.121437:285' b'120.785301:590'\n",
      " b'117.846016:866' b'117.630898:713' b'117.577415:325' b'117.014862:624'\n",
      " b'115.379265:416' b'113.632561:577' b'112.864334:849' b'109.799744:786'\n",
      " b'108.610672:789' b'107.180893:247' b'106.014206:639' b'103.654694:618'\n",
      " b'101.115891:293' b'97.774422:768' b'96.630348:698' b'95.063042:179'\n",
      " b'94.800751:636' b'93.384766:583' b'93.150208:326' b'91.545967:263'\n",
      " b'91.374107:612' b'90.138550:258' b'87.170784:414' b'85.042686:764'\n",
      " b'83.974625:324' b'83.918335:532' b'83.325462:217' b'82.908318:223'\n",
      " b'82.719536:522' b'82.296394:195' b'79.370872:648' b'76.031372:551'\n",
      " b'75.765137:141' b'75.003059:261' b'74.931358:426' b'73.599800:472'\n",
      " b'71.520683:587' b'71.324913:328' b'70.993042:246' b'70.743187:788'\n",
      " b'70.220467:493' b'69.489159:488' b'69.443878:104' b'68.150597:406'\n",
      " b'65.080688:267' b'64.889626:445' b'64.393417:446' b'63.366173:891'\n",
      " b'63.116508:790' b'61.547897:647' b'61.301849:491' b'60.932732:204'\n",
      " b'60.382362:697' b'60.060745:330' b'57.920269:432' b'57.296658:272'\n",
      " b'54.173370:411' b'52.071934:257' b'51.912212:433' b'51.800156:205'\n",
      " b'49.534134:700' b'48.221916:963' b'47.444706:540' b'47.108265:932'\n",
      " b'46.895653:23' b'45.642677:483' b'45.060204:403' b'44.669880:210'\n",
      " b'43.472534:752' b'42.247704:231' b'42.173561:232' b'41.871124:565'\n",
      " b'39.377506:309' b'39.209080:7' b'37.206589:792' b'34.251228:413'\n",
      " b'34.039120:905' b'33.509857:151' b'32.166958:824' b'32.143551:193'\n",
      " b'30.923807:284' b'29.648430:976' b'28.674950:273' b'26.542383:951'\n",
      " b'26.051573:874' b'24.379517:683' b'22.623852:765' b'21.829889:337'\n",
      " b'21.558224:12' b'21.308599:616' b'18.195160:691' b'15.688974:702'\n",
      " b'12.796104:684' b'8.622615:425' b'5.164956:633' b'4.568844:842'\n",
      " b'4.539775:490' b'3.465813:184' b'2.959346:543' b'-1.466746:856'\n",
      " b'-1.898361:810' b'-2.550367:770' b'-3.749318:514' b'-4.607335:203'\n",
      " b'-5.171169:667' b'-7.793096:753' b'-8.406100:422' b'-8.891047:444'\n",
      " b'-11.417400:143' b'-12.047046:81' b'-15.577780:253' b'-15.969985:333'\n",
      " b'-16.596788:922' b'-17.061556:798' b'-17.641687:870' b'-19.047642:959'\n",
      " b'-19.330639:198' b'-20.378620:987' b'-20.429693:219' b'-20.854736:492'\n",
      " b'-21.061438:719' b'-21.262135:431' b'-22.160612:834' b'-25.231434:288'\n",
      " b'-26.679314:687' b'-26.918751:547' b'-28.251181:173' b'-32.056526:915'\n",
      " b'-32.169476:230' b'-33.120430:954' b'-34.213394:449' b'-35.422848:494'\n",
      " b'-35.564438:260' b'-40.892643:67' b'-41.167965:467' b'-42.765781:520'\n",
      " b'-43.563496:430' b'-46.892708:482' b'-48.403519:933' b'-50.383331:259'\n",
      " b'-51.118473:746' b'-52.963455:46' b'-53.226185:535' b'-54.723297:501'\n",
      " b'-55.103809:730' b'-55.570614:314' b'-55.848427:674' b'-56.673252:207'\n",
      " b'-56.750462:310' b'-60.937420:428' b'-62.022243:623' b'-62.879436:399'\n",
      " b'-64.417099:677' b'-66.922691:144' b'-68.912933:209' b'-70.384850:549'\n",
      " b'-70.644707:930' b'-71.486168:221' b'-74.552597:244' b'-76.266762:228'\n",
      " b'-79.373947:558' b'-79.381561:516' b'-81.143112:953' b'-81.567551:448'\n",
      " b'-81.862144:906' b'-82.069786:11' b'-83.458046:336' b'-84.248192:835'\n",
      " b'-85.660378:347' b'-85.799583:27' b'-86.179420:250' b'-86.832481:956'\n",
      " b'-89.352165:999' b'-92.420891:689' b'-93.824898:663' b'-94.501236:658'\n",
      " b'-94.707565:961' b'-95.328918:927' b'-96.862762:948' b'-98.919403:662'\n",
      " b'-99.308029:200' b'-100.656853:405' b'-101.822563:484'\n",
      " b'-102.571724:573' b'-103.827438:262' b'-106.076218:589'\n",
      " b'-107.324852:970' b'-107.812363:234' b'-110.389999:998'\n",
      " b'-110.593216:721' b'-111.136597:668' b'-112.319481:885'\n",
      " b'-112.847176:275' b'-113.552902:377' b'-114.973068:703'\n",
      " b'-115.287666:169' b'-115.447899:621' b'-115.965286:943'\n",
      " b'-116.604057:359' b'-117.395714:159' b'-119.252815:265'\n",
      " b'-119.665390:423' b'-120.287125:820' b'-120.641800:308'\n",
      " b'-121.762794:774' b'-122.577774:952' b'-127.099350:92'\n",
      " b'-127.859718:269' b'-127.864960:595' b'-127.885284:40'\n",
      " b'-130.197144:680' b'-131.671494:135' b'-132.061234:180'\n",
      " b'-133.715775:593' b'-133.941498:178' b'-134.940979:136'\n",
      " b'-138.288879:964' b'-139.632797:174' b'-139.788544:539'\n",
      " b'-139.903610:787' b'-140.445923:307' b'-140.525620:188'\n",
      " b'-142.031311:277' b'-142.596664:78' b'-143.797577:707'\n",
      " b'-144.443604:975' b'-147.968445:211' b'-148.384872:8' b'-149.637665:878'\n",
      " b'-149.653778:496' b'-151.529282:712' b'-153.014908:706'\n",
      " b'-154.012558:355' b'-155.059540:533' b'-155.223633:236'\n",
      " b'-155.232742:163' b'-156.065842:233' b'-156.443573:759'\n",
      " b'-158.059753:775' b'-158.140594:172' b'-158.263550:911'\n",
      " b'-158.301971:171' b'-159.824158:31' b'-162.103897:242'\n",
      " b'-162.711380:528' b'-168.046494:564' b'-170.264511:947'\n",
      " b'-171.486771:728' b'-172.189941:936' b'-173.939163:981'\n",
      " b'-174.853012:481' b'-174.941513:576' b'-176.429535:270'\n",
      " b'-177.401505:887' b'-178.186646:944' b'-178.192688:201'\n",
      " b'-178.845200:225' b'-180.699341:9' b'-180.827637:989' b'-182.676895:458'\n",
      " b'-186.225845:895' b'-186.716141:478' b'-186.756744:794'\n",
      " b'-188.003036:429' b'-188.561264:152' b'-188.967316:157'\n",
      " b'-189.398254:311' b'-191.251190:756' b'-193.287277:342'\n",
      " b'-193.517136:227' b'-193.601501:507' b'-196.191635:106'\n",
      " b'-196.472794:686' b'-199.143433:699' b'-201.313461:248'\n",
      " b'-201.851044:614' b'-203.159271:495' b'-203.309265:499'\n",
      " b'-203.680908:400' b'-203.887772:424' b'-206.064011:266'\n",
      " b'-214.726028:51' b'-216.878525:548' b'-217.852356:111'\n",
      " b'-218.313522:653' b'-218.463165:24' b'-220.968475:661'\n",
      " b'-224.143707:525' b'-225.739548:925' b'-229.761642:487'\n",
      " b'-230.075272:692' b'-233.329788:512' b'-234.863998:990'\n",
      " b'-235.082596:313' b'-236.038666:80' b'-236.846832:340'\n",
      " b'-236.921158:381' b'-237.301193:871' b'-240.085388:439'\n",
      " b'-243.348495:855' b'-243.354187:382' b'-243.612106:327'\n",
      " b'-243.791168:591' b'-244.450546:334' b'-245.000336:271'\n",
      " b'-245.115036:777' b'-245.277176:945' b'-245.425400:161'\n",
      " b'-247.479523:71' b'-250.276642:59' b'-250.440704:286' b'-251.668213:451'\n",
      " b'-252.247986:941' b'-252.498489:139' b'-252.992737:843'\n",
      " b'-253.612457:18' b'-255.339066:74' b'-255.407028:724' b'-256.403717:79'\n",
      " b'-257.392242:942' b'-258.264557:519' b'-260.522736:238'\n",
      " b'-261.041443:168' b'-261.447784:371' b'-262.878784:194'\n",
      " b'-264.629669:167' b'-264.801483:306' b'-265.960358:679'\n",
      " b'-266.066925:102' b'-266.675873:410' b'-268.036316:118'\n",
      " b'-271.173798:75' b'-272.784180:124' b'-273.329590:294'\n",
      " b'-274.059662:901' b'-274.122131:385' b'-275.081299:701'\n",
      " b'-276.717316:443' b'-277.253448:315' b'-279.066864:580'\n",
      " b'-280.405975:274' b'-282.663391:858' b'-285.376251:166'\n",
      " b'-285.633667:931' b'-288.118408:671' b'-288.429077:249'\n",
      " b'-288.501007:122' b'-289.773712:42' b'-290.146027:99' b'-292.529175:115'\n",
      " b'-299.879089:502' b'-300.152863:43' b'-301.563690:364'\n",
      " b'-302.148224:318' b'-302.528381:187' b'-302.999207:921'\n",
      " b'-303.432800:780' b'-306.272125:748' b'-306.547943:588'\n",
      " b'-313.071594:529' b'-315.188507:303' b'-319.452454:884'\n",
      " b'-320.193970:649' b'-322.339966:695' b'-322.687531:113'\n",
      " b'-325.361816:461' b'-325.537750:833' b'-326.306885:801'\n",
      " b'-326.782806:630' b'-328.091492:240' b'-330.511444:563'\n",
      " b'-331.553253:640' b'-332.050140:162' b'-332.443604:584'\n",
      " b'-334.438324:15' b'-334.589966:183' b'-339.247070:112'\n",
      " b'-341.651550:690' b'-343.661987:341' b'-344.549194:156'\n",
      " b'-345.805725:177' b'-345.996735:30' b'-346.599304:47' b'-349.242188:54'\n",
      " b'-351.746674:912' b'-352.711121:992' b'-352.883453:362'\n",
      " b'-354.987427:291' b'-355.990021:13' b'-356.923340:857'\n",
      " b'-361.417877:743' b'-361.714874:145' b'-365.787048:28' b'-365.911438:53'\n",
      " b'-366.940796:222' b'-368.583405:239' b'-369.400879:123'\n",
      " b'-369.846619:348' b'-371.570251:197' b'-372.307251:319'\n",
      " b'-372.870911:343' b'-374.163483:741' b'-376.706970:83'\n",
      " b'-377.792877:100' b'-379.096161:213' b'-380.306885:977'\n",
      " b'-380.476685:335' b'-380.869537:356' b'-381.054413:735'\n",
      " b'-381.450958:749' b'-381.669342:105' b'-382.187958:816'\n",
      " b'-383.960571:82' b'-384.644287:196' b'-385.102173:158'\n",
      " b'-385.516205:379' b'-386.589203:537' b'-392.423981:214'\n",
      " b'-394.270386:77' b'-395.620728:190' b'-395.953430:474'\n",
      " b'-396.356293:252' b'-397.101959:86' b'-397.228210:825'\n",
      " b'-397.975464:331' b'-399.839844:988' b'-400.035217:191'\n",
      " b'-403.418701:287' b'-403.979340:354' b'-404.908966:226'\n",
      " b'-407.190857:738' b'-408.202026:465' b'-408.426788:4' b'-409.441193:361'\n",
      " b'-411.137299:296' b'-412.714020:603' b'-413.467926:329'\n",
      " b'-414.115143:212' b'-416.874542:669' b'-417.235199:117'\n",
      " b'-417.787476:127' b'-418.652649:280' b'-420.705170:295'\n",
      " b'-423.445282:320' b'-423.468781:96' b'-424.224792:241'\n",
      " b'-426.297852:634' b'-426.882568:434' b'-427.088531:2' b'-428.382599:278'\n",
      " b'-429.018463:160' b'-433.798340:349' b'-433.831696:345'\n",
      " b'-435.720123:165' b'-436.024963:729' b'-436.192749:87'\n",
      " b'-437.241394:119' b'-437.877808:175' b'-440.960449:91'\n",
      " b'-442.651581:322' b'-442.746399:45' b'-443.163788:973'\n",
      " b'-444.281860:890' b'-445.237701:121' b'-446.326752:132'\n",
      " b'-446.352325:615' b'-447.723602:332' b'-448.879700:611'\n",
      " b'-451.009979:164' b'-452.476135:25' b'-452.534973:390' b'-453.128998:85'\n",
      " b'-454.024323:56' b'-457.996918:76' b'-458.011353:181' b'-458.465210:89'\n",
      " b'-463.782288:229' b'-472.145203:304' b'-475.333099:5' b'-476.866425:279'\n",
      " b'-478.078094:940' b'-479.155396:979' b'-479.656921:10'\n",
      " b'-479.954956:128' b'-480.394745:456' b'-480.760742:19'\n",
      " b'-481.665924:290' b'-482.528320:393' b'-482.581757:913'\n",
      " b'-484.140869:452' b'-486.362305:300' b'-490.361725:101'\n",
      " b'-490.400970:450' b'-490.501404:153' b'-493.033813:366'\n",
      " b'-498.134460:289' b'-499.095520:147' b'-499.179596:95'\n",
      " b'-499.437958:150' b'-500.842957:939' b'-501.688660:218'\n",
      " b'-505.708710:473' b'-505.986847:302' b'-509.872589:676'\n",
      " b'-512.293396:206' b'-517.632446:395' b'-518.905029:14'\n",
      " b'-520.798279:370' b'-521.400146:37' b'-521.909302:763'\n",
      " b'-523.112854:972' b'-527.657593:110' b'-529.512329:140'\n",
      " b'-536.023193:312' b'-536.322876:374' b'-543.523315:292'\n",
      " b'-543.597229:202' b'-545.373291:189' b'-547.653442:130'\n",
      " b'-550.935730:93' b'-552.993774:477' b'-558.331177:378'\n",
      " b'-558.368164:114' b'-563.663574:983' b'-564.668701:73' b'-569.149170:36'\n",
      " b'-570.056824:62' b'-570.380005:863' b'-570.837097:88' b'-576.897095:358'\n",
      " b'-578.786316:84' b'-579.419006:97' b'-585.628113:48' b'-586.436584:586'\n",
      " b'-587.382812:383' b'-589.338318:357' b'-589.563599:367'\n",
      " b'-590.030151:66' b'-590.437744:352' b'-591.159058:41' b'-593.369507:268'\n",
      " b'-595.503845:52' b'-596.364746:853' b'-599.924194:21' b'-602.828857:109'\n",
      " b'-604.180481:955' b'-606.460510:176' b'-608.250305:394'\n",
      " b'-608.774048:61' b'-609.079590:116' b'-609.805176:69' b'-610.083374:70'\n",
      " b'-610.776428:32' b'-613.760193:44' b'-614.120056:68' b'-614.425232:138'\n",
      " b'-615.519897:129' b'-621.390869:524' b'-627.116211:39'\n",
      " b'-628.523071:376' b'-631.628540:305' b'-636.052124:34'\n",
      " b'-636.779114:914' b'-640.095703:137' b'-642.567322:126'\n",
      " b'-647.595032:386' b'-652.126953:346' b'-652.248596:6' b'-662.094299:55'\n",
      " b'-664.856567:50' b'-665.848633:392' b'-668.172791:98' b'-670.131714:397'\n",
      " b'-670.180542:20' b'-670.817871:996' b'-677.295288:22' b'-679.655884:893'\n",
      " b'-680.433044:369' b'-688.252380:38' b'-692.685791:317' b'-696.307983:72'\n",
      " b'-696.487000:994' b'-696.736084:384' b'-697.365967:360'\n",
      " b'-701.053528:107' b'-702.588074:17' b'-709.739990:388'\n",
      " b'-713.066101:148' b'-716.471008:142' b'-722.637817:363'\n",
      " b'-730.443542:339' b'-731.611450:108' b'-734.973328:365'\n",
      " b'-735.422607:991' b'-753.248962:125' b'-755.210266:316'\n",
      " b'-759.345337:389' b'-771.197205:986' b'-785.781616:375'\n",
      " b'-799.195923:368' b'-809.601257:57' b'-817.644775:237' b'-832.417175:33'\n",
      " b'-838.966370:49' b'-839.608765:350' b'-841.657410:396'\n",
      " b'-871.954529:120' b'-875.521118:64' b'-875.647644:391'\n",
      " b'-877.396240:500' b'-885.153992:353' b'-885.222595:149'\n",
      " b'-886.784241:35' b'-887.808716:297' b'-889.184692:997'\n",
      " b'-894.974182:131' b'-899.001038:739' b'-912.834595:597'\n",
      " b'-913.553040:146' b'-914.563232:133' b'-915.352844:344'\n",
      " b'-921.376709:995' b'-921.399597:993' b'-925.248779:103'\n",
      " b'-949.641663:715' b'-950.522522:63' b'-955.211182:29' b'-964.210632:387'\n",
      " b'-977.646851:58' b'-994.901672:26' b'-997.362366:726'\n",
      " b'-1047.918091:351' b'-1051.183350:65' b'-1063.572266:0'\n",
      " b'-1094.195801:3']\n"
     ]
    }
   ],
   "source": [
    "# 客户端请求\n",
    "import datetime\n",
    "import argparse\n",
    "from functools import partial\n",
    "import os\n",
    "import sys\n",
    "\n",
    "from PIL import Image\n",
    "import numpy as np\n",
    "from attrdict import AttrDict\n",
    "import struct\n",
    "import tritonclient.grpc.model_config_pb2 as mc\n",
    "import tritonclient.http as httpclient\n",
    "from tritonclient.utils import InferenceServerException\n",
    "from tritonclient.utils import triton_to_np_dtype\n",
    "import json,time\n",
    "import pysnooper\n",
    "# pip3 install Pillow\n",
    "import requests\n",
    "import base64\n",
    "\n",
    "\n",
    "# @pysnooper.snoop()\n",
    "def parse_model(model_metadata, model_config):\n",
    "    \"\"\"\n",
    "    Check the configuration of a model to make sure it meets the\n",
    "    requirements for an image classification network (as expected by\n",
    "    this client)\n",
    "    \"\"\"\n",
    "    if len(model_metadata.inputs) != 1:\n",
    "        raise Exception(\"expecting 1 input, got {}\".format(\n",
    "            len(model_metadata.inputs)))\n",
    "    if len(model_metadata.outputs) != 1:\n",
    "        raise Exception(\"expecting 1 output, got {}\".format(\n",
    "            len(model_metadata.outputs)))\n",
    "\n",
    "    if len(model_config.input) != 1:\n",
    "        raise Exception(\n",
    "            \"expecting 1 input in model configuration, got {}\".format(\n",
    "                len(model_config.input)))\n",
    "\n",
    "    input_metadata = model_metadata.inputs[0]\n",
    "    input_config = model_config.input[0]\n",
    "    output_metadata = model_metadata.outputs[0]\n",
    "\n",
    "    if output_metadata.datatype != \"FP32\":\n",
    "        raise Exception(\"expecting output datatype to be FP32, model '\" +\n",
    "                        model_metadata.name + \"' output type is \" +\n",
    "                        output_metadata.datatype)\n",
    "\n",
    "    # Output is expected to be a vector. But allow any number of\n",
    "    # dimensions as long as all but 1 is size 1 (e.g. { 10 }, { 1, 10\n",
    "    # }, { 10, 1, 1 } are all ok). Ignore the batch dimension if there\n",
    "    # is one.\n",
    "    output_batch_dim = (model_config.max_batch_size > 0)\n",
    "    non_one_cnt = 0\n",
    "    for dim in output_metadata.shape:\n",
    "        if output_batch_dim:\n",
    "            output_batch_dim = False\n",
    "        elif dim > 1:\n",
    "            non_one_cnt += 1\n",
    "            if non_one_cnt > 1:\n",
    "                raise Exception(\"expecting model output to be a vector\")\n",
    "\n",
    "    # Model input must have 3 dims, either CHW or HWC (not counting\n",
    "    # the batch dimension), either CHW or HWC\n",
    "    input_batch_dim = (model_config.max_batch_size > 0)\n",
    "    expected_input_dims = 3 + (1 if input_batch_dim else 0)\n",
    "    if len(input_metadata.shape) != expected_input_dims:\n",
    "        raise Exception(\n",
    "            \"expecting input to have {} dimensions, model '{}' input has {}\".\n",
    "                format(expected_input_dims, model_metadata.name,\n",
    "                       len(input_metadata.shape)))\n",
    "\n",
    "    if type(input_config.format) == str:\n",
    "        FORMAT_ENUM_TO_INT = dict(mc.ModelInput.Format.items())\n",
    "        input_config.format = FORMAT_ENUM_TO_INT[input_config.format]\n",
    "\n",
    "    if ((input_config.format != mc.ModelInput.FORMAT_NCHW) and\n",
    "            (input_config.format != mc.ModelInput.FORMAT_NHWC)):\n",
    "        raise Exception(\"unexpected input format \" +\n",
    "                        mc.ModelInput.Format.Name(input_config.format) +\n",
    "                        \", expecting \" +\n",
    "                        mc.ModelInput.Format.Name(mc.ModelInput.FORMAT_NCHW) +\n",
    "                        \" or \" +\n",
    "                        mc.ModelInput.Format.Name(mc.ModelInput.FORMAT_NHWC))\n",
    "\n",
    "    if input_config.format == mc.ModelInput.FORMAT_NHWC:\n",
    "        h = input_metadata.shape[1 if input_batch_dim else 0]\n",
    "        w = input_metadata.shape[2 if input_batch_dim else 1]\n",
    "        c = input_metadata.shape[3 if input_batch_dim else 2]\n",
    "    else:\n",
    "        c = input_metadata.shape[1 if input_batch_dim else 0]\n",
    "        h = input_metadata.shape[2 if input_batch_dim else 1]\n",
    "        w = input_metadata.shape[3 if input_batch_dim else 2]\n",
    "\n",
    "    return (model_config.max_batch_size, input_metadata.name,\n",
    "            output_metadata.name, c, h, w, input_config.format,\n",
    "            input_metadata.datatype)\n",
    "\n",
    "\n",
    "def preprocess(img, format, dtype, c, h, w, scaling, protocol):\n",
    "    \"\"\"\n",
    "    Pre-process an image to meet the size, type and format\n",
    "    requirements specified by the parameters.\n",
    "    \"\"\"\n",
    "    # np.set_printoptions(threshold='nan')\n",
    "\n",
    "    if c == 1:\n",
    "        sample_img = img.convert('L')\n",
    "    else:\n",
    "        sample_img = img.convert('RGB')\n",
    "\n",
    "    resized_img = sample_img.resize((w, h), Image.BILINEAR)\n",
    "    resized = np.array(resized_img)\n",
    "    if resized.ndim == 2:\n",
    "        resized = resized[:, :, np.newaxis]\n",
    "\n",
    "    npdtype = triton_to_np_dtype(dtype)\n",
    "    typed = resized.astype(npdtype)\n",
    "\n",
    "    if scaling == 'INCEPTION':\n",
    "        scaled = (typed / 127.5) - 1\n",
    "    elif scaling == 'VGG':\n",
    "        if c == 1:\n",
    "            scaled = typed - np.asarray((128,), dtype=npdtype)\n",
    "        else:\n",
    "            scaled = typed - np.asarray((123, 117, 104), dtype=npdtype)\n",
    "    else:\n",
    "        scaled = typed\n",
    "\n",
    "    # Swap to CHW if necessary\n",
    "    if format == mc.ModelInput.FORMAT_NCHW:\n",
    "        ordered = np.transpose(scaled, (2, 0, 1))\n",
    "    else:\n",
    "        ordered = scaled\n",
    "\n",
    "    # Channels are in RGB order. Currently model configuration data\n",
    "    # doesn't provide any information as to other channel orderings\n",
    "    # (like BGR) so we just assume RGB.\n",
    "    return ordered\n",
    "\n",
    "\n",
    "\n",
    "model_name='resnet50'\n",
    "model_version='202208013'\n",
    "url = '9.135.92.226:20160'\n",
    "classes=1000\n",
    "\n",
    "triton_client = httpclient.InferenceServerClient(url=url, verbose=False, concurrency=1)\n",
    "\n",
    "# 获取模型的配置信息\n",
    "model_metadata = triton_client.get_model_metadata(model_name=model_name, model_version=model_version)\n",
    "print('模型信息：',model_metadata)\n",
    "model_config = triton_client.get_model_config(model_name=model_name, model_version=model_version)\n",
    "print('模型配置：',model_config)\n",
    "max_batch_size, input_name, output_name, c, h, w, format, dtype = parse_model(AttrDict(model_metadata), AttrDict(model_config))\n",
    "# max_batch_size, input_name, output_name, c, h, w, format, dtype = 0,'input_name','output_name',3,224,224,2,'FP32'\n",
    "print('请求参数：',max_batch_size, input_name, output_name, c, h, w, format, dtype)\n",
    "\n",
    "image_base64 ='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QmNrZ09iamMAAAABAAAAAAAAUkdCQwAAAAMAAAAAUmQgIGRvdWJAb+AAAAAAAAAAAABHcm4gZG91YkBv4AAAAAAAAAAAAEJsICBkb3ViQG/gAAAAAAAAAAAAQnJkVFVudEYjUmx0AAAAAAAAAAAAAAAAQmxkIFVudEYjUmx0AAAAAAAAAAAAAAAAUnNsdFVudEYjUHhsQFIAAAAAAAAAAAAKdmVjdG9yRGF0YWJvb2wBAAAAAFBnUHNlbnVtAAAAAFBnUHMAAAAAUGdQQwAAAABMZWZ0VW50RiNSbHQAAAAAAAAAAAAAAABUb3AgVW50RiNSbHQAAAAAAAAAAAAAAABTY2wgVW50RiNQcmNAWQAAAAAAAAAAABBjcm9wV2hlblByaW50aW5nYm9vbAAAAAAOY3JvcFJlY3RCb3R0b21sb25nAAAAAAAAAAxjcm9wUmVjdExlZnRsb25nAAAAAAAAAA1jcm9wUmVjdFJpZ2h0bG9uZwAAAAAAAAALY3JvcFJlY3RUb3Bsb25nAAAAAAA4QklNA+0AAAAAABAASAAAAAEAAgBIAAAAAQACOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD+AAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNJxAAAAAAAAoAAQAAAAAAAAACOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0ECAAAAAAAEAAAAAEAAAJAAAACQAAAAAA4QklNBB4AAAAAAAQAAAAAOEJJTQQaAAAAAAM7AAAABgAAAAAAAAAAAAAAkQAAAGQAAAADAGMAYQB0AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAABkAAAAkQAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAA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ABIAQQBkAG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAIABDAEMAAAABADhCSU0EBgAAAAAABwAEAAAAAQEA/+EM52h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDAgNzkuMTYwNDUxLCAyMDE3LzA1LzA2LTAxOjA4OjIxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06RG9jdW1lbnRJRD0iN0M0NEUzQjNGNUM1N0NCNUY5ODEyRjAxMEE2MUI5ODEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OTI1Zjk3YzktNjNmZS00OGZmLWIxNGMtMjVhYzY0YTA2YjI4IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9IjdDNDRFM0IzRjVDNTdDQjVGOTgxMkYwMTBBNjFCOTgxIiBkYzpmb3JtYXQ9ImltYWdlL2pwZWciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wOkNyZWF0ZURhdGU9IjIwMjEtMTEtMThUMTc6NDM6NDIrMDg6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTExLTIxVDIwOjM3OjQ2KzA4OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIxLTExLTIxVDIwOjM3OjQ2KzA4OjAwIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6OTI1Zjk3YzktNjNmZS00OGZmLWIxNGMtMjVhYzY0YTA2YjI4IiBzdEV2dDp3aGVuPSIyMDIxLTExLTIxVDIwOjM3OjQ2KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgKE1hY2ludG9zaCkiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDw/eHBhY2tldCBlbmQ9InciPz7/4gxYSUNDX1BST0ZJTEUAAQEAAAxITGlubwIQAABtbnRyUkdCIFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFjcHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0AAACBAAAABRyWFlaAAACGAAAABRnWFlaAAACLAAAABRiWFlaAAACQAAA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'\n",
    "byte_content=base64.b64decode(image_base64)\n",
    "filename = 'smallcat.jpg'\n",
    "file = open(filename,mode='wb')\n",
    "file.write(byte_content)\n",
    "file.close()\n",
    "\n",
    "image_data = preprocess(Image.open(filename), format, dtype, c, h, w, None,'http')\n",
    "batched_image_data = image_data\n",
    "    \n",
    "# Send request\n",
    "input = httpclient.InferInput(input_name, batched_image_data.shape, dtype)\n",
    "input.set_data_from_numpy(batched_image_data)\n",
    "output = httpclient.InferRequestedOutput(output_name, class_count=classes)\n",
    "\n",
    "response = triton_client.infer(model_name,[input],request_id=str(time.time()),model_version=model_version,outputs=[output])\n",
    "output_array = response.as_numpy(output_name)\n",
    "print('响应：',len(output_array),output_array)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cf5b6373-4b23-4e56-8fbc-3c7379627105",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
